using System.Reflection;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using xjjxmm.infrastructure.Common;
using XjjXmm.Infrastructure.Configuration;
using XjjXmm.Infrastructure.Constant;
using XjjXmm.Infrastructure.Exceptions;
using XjjXmm.Infrastructure.ToolKit;
using XjjXmm.Infrastructure.User;

namespace xjjxmm.infrastructure.Authorizations;

public class JwtAuthenticationMiddleware : IMiddleware
{
    private readonly TokenContext _tokenContext;
    private readonly IEnumerable<IAuthenticationMiddleware> _authenticationMiddlewares;

    public JwtAuthenticationMiddleware(TokenContext tokenContext,
        IEnumerable<IAuthenticationMiddleware> authenticationMiddlewares)
    {
        _tokenContext = tokenContext;
        _authenticationMiddlewares = authenticationMiddlewares;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        var frameConfig = ConfigHelper.GetSection<FrameworkConfig>(CommonConstant.FrameworkConfigKey);
        if (frameConfig?.Ignores?.Any(t => context.Request?.Path.Value?.ToLower().Contains(t) == true) == true)
        {
            await next(context);
            return;
        }

        var controllerActionDescriptor = context
            .GetEndpoint()?
            .Metadata
            .GetMetadata<ControllerActionDescriptor>();

        if (controllerActionDescriptor?.MethodInfo.GetCustomAttribute<AllowAnonymousAttribute>() != null)
        {
            await next(context);
            return;
        }

        if (controllerActionDescriptor?.ControllerTypeInfo.GetCustomAttribute<AllowAnonymousAttribute>() != null)
        {
            await next(context);
            return;
        }

        if (context.User.Identity?.IsAuthenticated != true)
        {
            throw new Exception("访问了未授权资源， 请重新登入");
        }

        if (_tokenContext.Id.IsNullOrEmpty())
        {
            throw new BussinessException("没有权限访问相应的资源");
        }


        foreach (var action in _authenticationMiddlewares)
        {
            await action.InvokeAsync(context);
        }

        await next(context);
    }
}